﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using E7.Native;

namespace Z1029.PhiPlayer.OpenSource
{
    public class HitEffectManager : MonoBehaviour
    {
        const int MaxTapSoundsStream = 6;
        const int MaxFlickSoundsStream = 4;
        const int MaxDragSoundsStream = 8;

        public class HitSoundPlayer
        {
            public AudioSource player;
            public int soundID;
            public bool isPlaying;
            public int anaSid;
            HitEffectManager manager;
            float timer;
            float clipLength;

            public HitSoundPlayer(int SoundID)
            {
                manager = LevelController.instance.hitEffectManager;
                GameObject g = new GameObject("HitSoundPlayer", typeof(AudioSource));
                g.transform.parent = manager.hitEffectSound.transform;
                player = g.GetComponent<AudioSource>();
                player.volume = LevelController.hitSoundsVolume;
                soundID = SoundID - 1;
                player.clip = manager.hitSounds[soundID];
                clipLength = manager.hitSounds[soundID].length;
            }

            public void Update()
            {
                if (!isPlaying)
                    return;
                timer += (float)LevelController.instance.progressControl.deltaDspTime / 60.0f;
                if (timer > clipLength)
                {
                    isPlaying = false;
                    player.Stop();
                    //player.gameObject.name = "HitSoundPlayer";
                }
            }

            public void Play(bool Interrupt)
            {
                player.time = 0;
                player.Play();
                timer = 0;
                isPlaying = true;
            }
        }

        public bool useNativeAudio = false;

        public GameObject perfectEffect, goodEffect;
        public GameObject[] badEffects;
        //bad有好多
        public Dictionary<int, List<HitSoundPlayer>> soundPool;

        [Header("For Android")]
        //public NativeAudioPointer[] hitSoundsPointers;
        //NativeSource[] nativeSources;

        [Header("For Other Platform")]
        public AudioClip[] hitSounds;
        public AudioSource hitEffectSound;

        private void Start()
        {
            float num = (LevelController.noteSize + LevelController.instance.noteSizeOffset) * 10 / 2.55f;
            perfectEffect.transform.localScale = new Vector3(num, num, num);
            goodEffect.transform.localScale = new Vector3(num, num, num);
            float num1 = (LevelController.noteSize + LevelController.instance.noteSizeOffset);
            for (int i = 0; i < badEffects.Length; i++)
            {
                badEffects[i].transform.localScale = new Vector3(num1, num1, num1);
            }
            useNativeAudio = PlayerPrefs.GetInt("UseNativeAudio", 1) == 1;
            useNativeAudio = (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer) && useNativeAudio;
            if (useNativeAudio) InitNASounds();
            else InitHitSounds();
        }

        public void InitHitSounds()
        {
            hitEffectSound.volume = LevelController.hitSoundsVolume;
            soundPool = new Dictionary<int, List<HitSoundPlayer>>();
            int i;

            List<HitSoundPlayer> SEPool = new List<HitSoundPlayer>();
            for (i = 0; i < MaxTapSoundsStream; i++)
            {
                SEPool.Add(new HitSoundPlayer(1));
            }
            soundPool.Add(1, SEPool);

            SEPool = new List<HitSoundPlayer>();
            for (i = 0; i < MaxDragSoundsStream; i++)
            {
                SEPool.Add(new HitSoundPlayer(2));
            }
            soundPool.Add(2, SEPool);

            SEPool = new List<HitSoundPlayer>();
            for (i = 0; i < MaxDragSoundsStream; i++)
            {
                SEPool.Add(new HitSoundPlayer(3));
            }
            soundPool.Add(3, SEPool);
        }

        public void InitNASounds()
        {
            /*NativeAudio.Initialize(new NativeAudio.InitializationOptions
            {
                androidAudioTrackCount = 16,
            });
            hitSoundsPointers = new NativeAudioPointer[hitSounds.Length];
            nativeSources = new NativeSource[hitSounds.Length];
            for (int i = 0; i < hitSounds.Length; i++)
            {
                hitSoundsPointers[i] = NativeAudio.Load(hitSounds[i]);
                nativeSources[i].SetVolume(LevelController.hitSoundsVolume);
            }*/
        }

        /// <summary>
        /// 显示打击特效 (soundID写0没有声音，写1播放实际0的音效)
        /// </summary>
        public void ShowEffect(Note.HitACC acc, Vector3 pos, Transform parent, int soundID, NoteType type)
        {
            if (soundID != 0 && acc != Note.HitACC.Bad) PlayHitSoundById(soundID);
            GameObject effect = null;
            switch (acc)
            {
                case Note.HitACC.Perfect:
                    effect = Instantiate(perfectEffect, pos, new Quaternion());
                    //effect.transform.parent = parent;
                    break;
                case Note.HitACC.Good:
                    effect = Instantiate(goodEffect, pos, new Quaternion());
                    break;
                case Note.HitACC.Bad:
                    effect = Instantiate(badEffects[(int)type], pos, new Quaternion());
                    effect.transform.parent = parent;
                    effect.transform.localEulerAngles = Vector3.zero;
                    break;
            }
            Destroy(effect, 0.5f);
        }

        public void PlayHitSoundById(int soundID)
        {
            if (LevelController.hitSoundsVolume == 0)
                return;
            if (useNativeAudio)
            {
                //nativeSources[soundID - 1].Play(hitSoundsPointers[soundID - 1]);
            }
            else
            {
                List<HitSoundPlayer> SEPool = soundPool[soundID];
                for (int i = 0; i < SEPool.Count; i++)
                {
                    if (!SEPool[i].isPlaying)
                    {
                        SEPool[i].Play(false);
                        return;
                    }
                }
                SEPool[0].Play(true);
            }
        }

        private void Update()
        {
            if (!useNativeAudio)
                UpdateSoundPool();
        }

        public void UpdateSoundPool()
        {
            int i;
            for (i = 1; i < 4; i++)
            {
                soundPool[i].ForEach(x => x.Update());
            }
        }

        void OnDestroy()
        {
            // Clean up when done
            //if(useNativeAudio)
            //NativeAudio.Dispose();
        }
    }
}